#ifndef __ANIMTRACK_H__
#define __ANIMTRACK_H__

#include "IGame/IGameType.h"
#include "Skeleton.h"
#include <vector>


class AnimFrame
{
public:

	AnimFrame( int numBones )
	{
		m_BonesTransform.resize( numBones );
	}

	void AddBoneTransform( const GMatrix& transform, int boneID )
	{
		m_BonesTransform[boneID] = transform;
	}

	const GMatrix& GetBoneTransform( int i ) const
	{
		return m_BonesTransform[i];
	}

	int GetNumTransform( void ) const
	{
		return (int)m_BonesTransform.size();
	}

private:

	typedef	std::vector<GMatrix>	bonesTransformVec;

	bonesTransformVec		m_BonesTransform;
};



class AnimTrack
{
public:

	int Build( IGameObject* obj, Skeleton* skeleton )
	{
		int i, j, time;

		int animStart = (int)( GetCOREInterface()->GetAnimRange().Start() / GetTicksPerFrame() );
		int animEnd   = (int)( GetCOREInterface()->GetAnimRange().End() / GetTicksPerFrame() );

		const int numAnimFrames = ( animEnd - animStart ) + 1;
		const int numBones = skeleton->GetNumBones();

		IGameNode* node;
		Bone* bone, * parent;

		m_AnimFrames.reserve( numAnimFrames );

		for ( i = 0; i < numAnimFrames; ++i )
		{
			time = i * GetTicksPerFrame();
			AnimFrame frame( numBones );

			for ( j = 0; j < numBones; ++j )
			{
				bone = skeleton->GetRawBone( j );
				node = bone->GetMaxNode();
				GMatrix transform = node->GetWorldTM( time );

				if ( bone->GetParentID() != -1 )	/* iOrange - if not root bone, inverse transformation */
				{
					parent = bone->GetParent();
					node = parent->GetMaxNode();
					GMatrix parentTM = node->GetWorldTM( time );
					if ( -1 == parentTM.Parity() )
					{
						parentTM = parentTM.Inverse();
						GMatrix m = parentTM;
						memset( &parentTM, 0, sizeof( parentTM ) );
						parentTM -= m;
					}
					else
						parentTM = parentTM.Inverse();

					transform *= parentTM;
				}

				frame.AddBoneTransform( transform, bone->GetID() );
			}

			m_AnimFrames.push_back( frame );
		}

		return TRUE;
	}

	void WriteToStream( std::stringstream& ss )
	{
		int i, j;

		ss << this->GetNumFrames() << std::endl;

		for ( i = 0; i < this->GetNumFrames(); ++i )
		{
			const AnimFrame& frame = this->GetAnimFrame( i );
			for ( j = 0; j < frame.GetNumTransform(); ++j )
			{
				const GMatrix& mat = frame.GetBoneTransform( j );
				Point3 offset = mat.Translation();
				Quat rotation = mat.Rotation();

				ss << offset.x << " " << offset.y << " " << offset.z << std::endl;
				ss << rotation.x << " " << rotation.y << " " << rotation.z << " " << rotation.w << std::endl;
			}
		}
	}



	int GetNumFrames( void ) const
	{
		return (int)m_AnimFrames.size();
	}

	const AnimFrame& GetAnimFrame( int i ) const
	{
		return m_AnimFrames[i];
	}


protected:

	typedef std::vector<AnimFrame>	framesVec;

	framesVec		m_AnimFrames;
};

#endif

